var express = require('express'),
    app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server);

//specify the html we will use
app.use('/', express.static(__dirname + '/www'));

server.listen(3000); //for local test

var Set = function() {
    this.arr = [];
};

Set.prototype = {
    add: function(x) {
        var flag = true;
        for (var i = this.arr.length - 1; i >= 0; i--) {
            if (this.arr[i] == x) {
                flag = false;
                break;
            }
        }
        if (flag === true) {
            this.arr.push(x);
        }
        return flag;
    },
    size: function() {
        return this.arr.length;
    },
    get: function(i) {
        return this.arr[i];
    },
    removeAt: function(i){
        this.arr.splice(i,1);
    },
    remove: function (obj) {
        var i = this.arr.indexOf(obj);
        this.arr.splice(i,1);
    },
};

function chatServer(){
	this.nameSet = new Set();//for all the online users
	this.nameSet.add("robot");
	this.sktList = {};//for all the sockets
	var self = this;
	this.init = function(){
		//handle the socket
		io.sockets.on('connection', function(socket) {
		    //login
		    socket.on("login", function(nickname) {
		        if (self.nameSet.add(nickname) === true) {
		            sktList[nickname] = socket;
		            socket.nickname = nickname;
		            socket.usrIndex = sktList.length;
		            // var nowTime = Math.floor(new Date().getTime() / 1000);
		            socket.lastSpeakTime = self.getCurTime();
		            io.sockets.emit('loginSuccess', self.nameSet); //confirm the connection
		        } else if (self.nameSet.add(nickname) === false) {
		            socket.emit('loginFailed', nickname); //send back nameSet
		        }

		    });
		    //p2p message
		    socket.on("p2pMsg", function(from, dest, msg) {
		        if (from in self.sktList) {
		            var nowTime = Math.floor(new Date().getTime() / 1000);
		            self.sktList[from].lastSpeakTime = nowTime;
		            for (var nickname in self.sktList) {
		                if (nickname == dest) {
		                    self.sktList[nickname].emit("p2pMsg", from, msg);
		                }
		            }

		        }

		    });
		    //new image get
		    socket.on('p2pImg', function(from, dest, imgData) {
		        if (from in self.sktList) {
		            var nowTime = Math.floor(new Date().getTime() / 1000);
		            self.sktList[from].lastSpeakTime = nowTime;
		            for (var nickname in self.sktList) {
		                if (nickname == dest) {
		                    self.sktList[nickname].emit("p2pImg", from, imgData);
		                }
		            }
		        }
		    });
		    // ping-pong check
		    socket.on('ping', function(data) {
		        // if (data.type == 'EXEC') {
		        //     io.emit('broadcast', {
		        //         type: 'EXEC'
		        //     });
		        // }
		        // console.warn(data);
		        pong(data.nick);
		    });
		    //logout
		    socket.on("disconnect", function() {
		        for (var nickname in self.sktList) {
		            if (nickname == socket.nickname) {
		                self.sktList[nickname] = null;
		            }
		        }
		        io.sockets.emit("logout", socket.nickname);
		    });
		});
		setInterval(self.pong, 1000);
	};
	this.getCurTime = function(){
		var nowTime = Math.floor(new Date().getTime() / 1000);
		return nowTime;
	};
	this.pong = function(){
	    var nowTime = Math.floor(new Date().getTime() / 1000);
	    // for(var nickname in sktList) {
	    if (nick in self.sktList) {
	        // console.log(self.sktList);
	        var socket = self.sktList[nick];
	        // }
	        if (socket.lastSpeakTime && nowTime - socket.lastSpeakTime > 1 * 60) {
	            socket.emit('pm', {
	                nick: nick,
	                msg: 'you are disconnect due to long time no talk',
	                // type: "DISCONNECT"
	            });
	            socket.disconnect();
	            io.sockets.emit("disconnected", socket.nickname);
	            // delete self.onlineUser[id];
	            nameSet.remove(nick);
	            socket = null;
	            self.sktList[nick] = null;
	            delete self.sktList[nick];            
	        } else {
	            // data = { "nick":nick, "msg": "pong-back" };
	            // socket.emit("pong", data);
	            console.warn(nick+" online");
	        }
	    } else {
	        // console.log("empty pong");
	        var data = {"msg":"empty pong to all clients"};
	        io.sockets.emit("pong", data);
	    }
	};
}



//backup
var nameSet = new Set();//for all the online users
nameSet.add("robot");
var sktList = {};//for all the sockets

//handle the socket
io.sockets.on('connection', function(socket) {
    //login
    socket.on("login", function(nickname) {
        if (nameSet.add(nickname) === true) {
            sktList[nickname] = socket;
            socket.nickname = nickname;
            socket.usrIndex = sktList.length;
            var nowTime = Math.floor(new Date().getTime() / 1000);
            socket.lastSpeakTime = nowTime;
            io.sockets.emit('loginSuccess', nameSet); //confirm the connection
        } else if (nameSet.add(nickname) === false) {
            socket.emit('loginFailed', nickname); //send back nameSet
        }

    });
    //p2p message
    socket.on("p2pMsg", function(from, dest, msg) {
        if (from in sktList) {
            var nowTime = Math.floor(new Date().getTime() / 1000);
            sktList[from].lastSpeakTime = nowTime;

            for (var nickname in sktList) {
                if (nickname == dest) {
                    sktList[nickname].emit("p2pMsg", from, msg);
                }
            }

        }

    });
    //new image get
    socket.on('p2pImg', function(from, dest, imgData) {
        if (from in sktList) {
            var nowTime = Math.floor(new Date().getTime() / 1000);
            sktList[from].lastSpeakTime = nowTime;
            for (var nickname in sktList) {
                if (nickname == dest) {
                    sktList[nickname].emit("p2pImg", from, imgData);
                }
            }
        }
    });
    // ping-pong check
    socket.on('ping', function(data) {
        // if (data.type == 'EXEC') {
        //     io.emit('broadcast', {
        //         type: 'EXEC'
        //     });
        // }
        // console.warn(data);
        pong(data.nick);
    });
    //logout
    socket.on("disconnect", function() {
        for (var nickname in sktList) {
            if (nickname == socket.nickname) {
                sktList[nickname] = null;
            }
        }
        io.sockets.emit("logout", socket.nickname);
    });
});

pong = function(nick) {
    // var self = this;
    // var users = [];
    var nowTime = Math.floor(new Date().getTime() / 1000);
    // for(var nickname in sktList) {
    if (nick in sktList) {
        // console.log(sktList);
        var socket = sktList[nick];
        // }
        if (socket.lastSpeakTime && nowTime - socket.lastSpeakTime > 1 * 60) {
            socket.emit('pm', {
                nick: nick,
                msg: 'you are disconnect due to long time no talk',
                // type: "DISCONNECT"
            });
            socket.disconnect();
            io.sockets.emit("disconnected", socket.nickname);
            // delete self.onlineUser[id];
            nameSet.remove(nick);
            socket = null;
            sktList[nick] = null;
            delete sktList[nick];            
        } else {
            // data = { "nick":nick, "msg": "pong-back" };
            // socket.emit("pong", data);
            console.warn(nick+" online");
        }
    } else {
        // console.log("empty pong");
        var data = {"msg":"empty pong to all clients"};
        io.sockets.emit("pong", data);
    }
};
// heart-beat
setInterval(pong, 1000);
